package org.flexspeedup.blog.admin.controllers
{
import flash.events.Event;
import flash.events.IEventDispatcher;

import mx.collections.ArrayCollection;
import mx.rpc.AsyncToken;
import mx.rpc.Responder;
import mx.rpc.events.FaultEvent;
import mx.rpc.remoting.mxml.RemoteObject;
import mx.utils.ObjectUtil;

import org.flexspeedup.blog.admin.types.Sections;
import org.flexspeedup.blog.events.NavigateToEvent;
import org.flexspeedup.blog.events.RemovePendingChangesEvent;
import org.flexspeedup.blog.models.MiniPost;
import org.flexspeedup.blog.models.ResultSet;
import org.flexspeedup.blog.types.ServiceType;
import org.flexspeedup.model.IListModel;
import org.flexspeedup.model.IListOption;
import org.swizframework.core.IDispatcherAware;

/**
 * Controlls all MiniBlog operations
 */
public class MiniBlogController implements IDispatcherAware, IEventDispatcher
{

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Creates a new instance of this class.
     */
    public function MiniBlogController()
    {
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    // services
    //----------------------------------
    [Inject(source="blogService")]
    /**
     * services bean
     */
    public var services:RemoteObject;
    
    //----------------------------------
    // miniBlogModel
    //----------------------------------
    [Inject(source="miniBlogModel")])
    /**
     * miniBlogModel bean
     */
    public var miniBlogModel:IListModel;

    //----------------------------------
    // categoryModel
    //----------------------------------
    [Inject(source="categoryModel")]
    /**
     * categoryModel bean
     */
    public var categoryModel:IListModel;

    //--------------------------------------------------------------------------
    //
    //  Methods - Mediators
    //
    //--------------------------------------------------------------------------    

    //----------------------------------
    //  changePostCategory
    //----------------------------------
    [Mediate(event="ChangePostCategoryEvent.ID", properties="category")]
    /**
     * Changes the selected category in the category model
     */
    public function changePostCategory(category:IListOption):void
    {
        categoryModel.selectedItem = category;
    }

    //----------------------------------
    //  getPosts
    //----------------------------------
    [Mediate(event="GetPostsEvent.ID", properties="page")]
    /**
     * Retrieves a of posts
     */
    public function getPosts(page:int):void
    {
        var token:AsyncToken = services.getOperation(ServiceType.GET_POSTS).send(page);
        token.addResponder(
            new Responder(
                getPosts_resultHandler,
                getPosts_faultHandler
            )
        );
    }
    
    //----------------------------------
    //  selectPost
    //----------------------------------
    [Mediate(event="SelectPostEvent.ID", properties="post")]
    /**
     * Selects a post in the model
     */
    public function selectPost(post:MiniPost):void
    {
        miniBlogModel.selectedItem = post;
    }

    //----------------------------------
    //  createNewPost
    //----------------------------------
    [Mediate(event="CreateNewPostEvent.ID")]
    /**
     * Creates a new MiniPost in the selectedItem property in the model
     */
    public function createNewPost():void
    {
        miniBlogModel.selectedItem = new MiniPost();
        dispatchEvent(new NavigateToEvent(Sections.EDIT_POST));    
    }
    
    //----------------------------------
    //  editSelectedPost
    //----------------------------------
    [Mediate(event="EditSelectedPostEvent.ID")]
    /**
     * Edits the post selected in the model
     */
    public function editSelectedPost():void
    {
        if (miniBlogModel.selectedItem)
            dispatchEvent(new NavigateToEvent(Sections.EDIT_POST));
    }
    
    //----------------------------------
    //  savePost
    //----------------------------------
    [Mediate(event="SavePostEvent.ID", properties = "post")]
    /**
     * Saves / updates a post
     */
    public function savePost(post:MiniPost):void
    {
        
        var newPost:MiniPost = 
            ObjectUtil.copy(miniBlogModel.selectedItem) as MiniPost;
        newPost.title = post.title;
        newPost.body = post.body;
        var token:AsyncToken = 
            services.getOperation(ServiceType.SAVE_POST).send(newPost);
        token.addResponder(
            new Responder(
                savePost_resultHandler,
                savePost_faultHandler
            )
        );
    }

    //--------------------------------------------------------------------------
    //
    //  Responders
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  getPosts_resultHandler
    //----------------------------------
    /**
     * @private
     */
    private function getPosts_resultHandler(data:Object):void
    {
        miniBlogModel.dataProvider = new ArrayCollection(data.result.items);
        miniBlogModel.resultSet = data.result as ResultSet;
    }    
    
    //----------------------------------
    //  getPosts_faultHandler
    //----------------------------------
    /**
     * @private
     */
    private function getPosts_faultHandler(info:Object):void
    {
        trace (FaultEvent(info).message);
    }
    
    //----------------------------------
    //  savePost_resultHandler
    //----------------------------------
    /**
     * @private
     */
    private function savePost_resultHandler(data:Object):void
    {
        var post:MiniPost = miniBlogModel.selectedItem as MiniPost;
        post.title = data.result.title;
        post.body = data.result.body;
        dispatchEvent(new RemovePendingChangesEvent())
    }    
    
    //----------------------------------
    //  savePost_faultHandler
    //----------------------------------
    /**
     * @private
     */
    private function savePost_faultHandler(info:Object):void
    {
        trace (FaultEvent(info).message);
    }
    
    //--------------------------------------------------------------------------
    //
    //  IDispathcerAware implementation
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  _dispatcher
    //----------------------------------
    /**
     *  @private
     */
    private var _dispatcher:IEventDispatcher;

    /**
     *  @private
     *  IDispatcherAware implementation
     */
    public function set dispatcher(dispatcher:IEventDispatcher):void
    {
        _dispatcher = dispatcher;
    }

    //--------------------------------------------------------------------------
    //
    //  IEventDispatcher implementation using swiz dispatcher
    //
    //--------------------------------------------------------------------------
    
    public function addEventListener(type:String, listener:Function, 
                                     useCapture:Boolean = false, 
                                     priority:int = 0, 
                                     useWeakReference:Boolean = false):void
    {
        _dispatcher.addEventListener(type, listener, useCapture, priority);
    }
    
    public function dispatchEvent(event:Event):Boolean
    {
        return _dispatcher.dispatchEvent(event);
    }
    
    public function hasEventListener(type:String):Boolean{
        return _dispatcher.hasEventListener(type);
    }
    
    public function removeEventListener(type:String, listener:Function, 
                                        useCapture:Boolean = false):void
    {
        _dispatcher.removeEventListener(type, listener, useCapture);
    }
    
    public function willTrigger(type:String):Boolean
    {
        return _dispatcher.willTrigger(type);
    }
}
}